/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Model;

import java.awt.Color;
import java.awt.Graphics;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Random;

/**
 *Lane constructs itself dynamically with respect to initial display size
 * @author Pro
 */
public class Lane implements Serializable {

    private int hLanes, vLanes, laneID, flow, laneLength, laneWidth, x, y, randCheck;
    private double carProb;
    private Lane[] lanes;
    private Color color;
    private Lights lights;
    private ArrayList<Car> cars;
    private Random random = new Random();

    /**
     *Constructor has three arguments of type integer
     * @param i is index of lane in lane array
     * @param j is the number of horizontal lanes
     * @param k is the number of vertical lanes
     */
    public Lane(int i, int j, int k) {

        cars = new ArrayList<Car>();
        carProb = 1.0;
        laneID = i;
        hLanes = j;
        vLanes = k;
        color = new Color(0x595454);

        if (laneID < hLanes) {

            flow = 0;
            laneLength = 800;
            laneWidth = 30;
            x = 0;
            y = ((laneLength / 2) - ((hLanes) * 35) / 2 + (laneID * 35));
            lights = new Lights(flow, (800 / 2 - (35 / 2) * vLanes) - 8, y);
        }

        if (laneID >= hLanes) {

            flow = 1;
            laneWidth = 800;
            laneLength = 30;
            x = ((laneWidth / 2) - ((vLanes) * 35) / 2) + ((laneID - hLanes) * 35);
            y = 0;
            lights = new Lights(flow, x, (800 / 2 + (35 / 2) * hLanes) - 2);
        }
    }

    /**
     *Public method is reference to lights of lane
     * @return value is of type Lights
     */
    public synchronized Lights getLights() {
        return this.lights;
    }

    /**
     *Public method is value of horizontal lanes
     * @return value is of type integer
     */
    public int gethLanes() {
        return hLanes;
    }

    /**
     *Public method is value of vertical lanes
     * @return value is of type integer
     */
    public int getvLanes() {
        return vLanes;
    }

    /**
     *Public method that set value of carProb
     * @param newCarProb is of type
     */
    public void setLanes(Lane[] lanes) {
        this.lanes = lanes;
    }

    public void setCarProb(int newCarProb) {

        carProb = newCarProb * 0.01;
    }

    /**
     *Public method returns the identifier for horizonal or vertical lane
     * @return the identifier for horizonal or vertical lane
     */
    public int getFlow() {
        return flow;
    }

    /**
     *Public method that return the reference for car array list
     * @return is of type Car<>
     */
    public synchronized ArrayList<Car> getCars() {
        return cars;
    }

    /**
     *Public method that draws lane when called by carDisplay
     * @param g is of type Graphics
     */
    public synchronized void draw(Graphics g) {

        g.setColor(color);
        g.fillRect(x, y, laneLength, laneWidth);

    }

    /**
     * Public method that creates new car dynamically
     */
    public synchronized void bingCar() {

        int i = cars.size();
        if (flow == 0) {
            if (i == 0 || cars.get(i - 1).getX() >= 0) {

                if (Math.random() <= carProb) {
                    Car car = new Car(i, y, flow, random.nextInt(3));
                    cars.add(car);
                }
            }

            if (i > 1 && cars.get(1).getX() >= 830) {

                cars.remove(0);
            }

        }

        if (flow == 1) {
            if (i == 0 || cars.get(i - 1).getY() <= 780) {

                if (Math.random() <= carProb) {
                    Car car = new Car(i, x, flow, random.nextInt(3));

                    cars.add(car);
                }
            }

            if (i > 1 && cars.get(1).getY() <= -30) {

                cars.remove(0);
            }
        }
    }

    public void overTake(int cIndex) {

boolean carBlocking = false;

        if (this.flow == 0) {

            if (laneID != lanes.length) {  // Check for if lane is last in list to avoid AoB Exception

                if (lanes[laneID + 1].getFlow() == flow) {

                    for (int i = 0; i < lanes[laneID + 1].cars.size(); ++i) {   // Loop for cars  Array list length

                        if (  (lanes[laneID + 1].cars.get(i).getX()) > (cars.get(cIndex).getX() - 30) && (lanes[laneID + 1].cars.get(i).getX()) < (cars.get(cIndex).getX() + 30)) {
                            
                            carBlocking = true;

                        }
                    }

                    if (!carBlocking){

                        // CHANGE LANES!!!!!!!!!!

                    }
                }
            } else {

                if (laneID != 0) {    // Check for if lane is first in list to avoid AoB Exception

                    if (lanes[laneID - 1].getFlow() == flow) {

                        for (int i = 0; i < lanes[laneID - 1].cars.size(); ++i) {   // Loop for cars  Array list length

                            if (  (lanes[laneID + 1].cars.get(i).getX()) > (cars.get(cIndex).getX() - 30) && (lanes[laneID + 1].cars.get(i).getX()) < (cars.get(cIndex).getX() + 30)) {

                                 carBlocking = true;

                            }
                        }

                        if (!carBlocking){

                            // CHANGE LANES!!!!!!!!!!!!

                        }
                    }
                }
            }
        }


        if (this.flow == 1){

            if (laneID != lanes.length) {

                if (lanes[laneID + 1].getFlow() == flow) {

                    for (int i = 0; i < lanes[laneID + 1].cars.size(); ++i) {

                        if ((lanes[laneID + 1].cars.get(i).getY()) > (cars.get(cIndex).getY() + 30) && (lanes[laneID + 1].cars.get(i).getY() + 30) > cars.get(cIndex).getY()) {

                            // CHANGE LANES!!!!!!!!!!!!
                        }
                    }
                }
            } else {

                if (laneID != 0) {

                    if (lanes[laneID - 1].getFlow() == flow) {

                        for (int i = 0; i < lanes[laneID - 1].cars.size(); ++i) {

                            if ((lanes[laneID - 1].cars.get(i).getY() - 30) < cars.get(cIndex).getY() || (lanes[laneID - 1].cars.get(i).getY() + 30) > cars.get(cIndex).getY()) {

                                // CHANGE LANES!!!!!!!!!!!!
                            }
                        }
                    }
                }
            }
        }


















    }

    public void checkCars(int carsLane) {
    }

    /**
     *Public method that Moves cars dynamically
     */
    public synchronized void moveCars() {

        int j = cars.size();

        if (this.flow == 0) {

            for (int i = 0; i < j; i++) {

                if (i != 0) {
                    if (this.lights.getGreen()) {

                        if (cars.get(i).getX() < (cars.get(i - 1).getX() - 25)) {

                            cars.get(i).move();
                        }

                    } else if (cars.get(i).getX() + 20 > this.lights.getX()) {

                        if (cars.get(i).getX() < (cars.get(i - 1).getX() - 25)) {

                            cars.get(i).move();
                        }
                    } else {

                        if (cars.get(i).getX() + 25 < this.lights.getX()) {

                            if (cars.get(i).getX() < (cars.get(i - 1).getX() - 25)) {

                                cars.get(i).move();

                            }
                        }
                    }
                } else {

                    if (this.lights.getGreen()) {

                        cars.get(i).move();

                    } else if (cars.get(i).getX() + 15 > this.lights.getX()) {

                        cars.get(i).move();
                    } else {

                        if (cars.get(i).getX() + 25 < (this.lights.getX())) {

                            cars.get(i).move();
                        }
                    }
                }
            }
        }
        if (this.flow == 1) {

            for (int i = 0; i < j; i++) {

                if (i != 0) {

                    if (this.lights.getGreen()) {

                        if (cars.get(i).getY() > (cars.get(i - 1).getY() + 25)) {

                            cars.get(i).move();
                        }
                    } else {

                        if ((cars.get(i).getY() - 5) < this.lights.getY()) {

                            if (cars.get(i).getY() > (cars.get(i - 1).getY() + 25)) {


                                cars.get(i).move();
                            }

                        } else if (cars.get(i).getY() > this.lights.getY() + 15) {

                            if (cars.get(i).getY() > (cars.get(i - 1).getY() + 25)) {

                                cars.get(i).move();
                            }
                        }
                    }
                } else {

                    if (this.lights.getGreen()) {

                        cars.get(i).move();

                    } else {

                        if ((cars.get(i).getY() - 5) < this.lights.getY()) {

                            cars.get(i).move();

                        } else if (cars.get(i).getY() > (this.lights.getY() + 15)) {

                            cars.get(i).move();
                        }
                    }
                }
            }
        }
    }
}
